package com.hongawen.utils;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @author hongawen
 * @version 1.0.0
 * @date 2021年04月30日 09:38
 */
@Component
@RequiredArgsConstructor
public class RedisUtil {

    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 切换redis数据片
     *
     * @param db 数据库片
     */
    public int switchRedisDb(int db) {
        LettuceConnectionFactory connectionFactory = (LettuceConnectionFactory) redisTemplate.getConnectionFactory();
        connectionFactory.setDatabase(db);
        int oldDb = connectionFactory.getDatabase();
        //刷新配置
        connectionFactory.afterPropertiesSet();
        //重置连接
        connectionFactory.resetConnection();
        redisTemplate.setConnectionFactory(connectionFactory);
        return oldDb;
    }


    /**
     * 删除某个Key
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 批量删除keys
     */
    public void deleteKeys(String... keys) {
        redisTemplate.delete(Arrays.asList(keys));
    }

    /**
     * 指定key的失效时间
     * 分钟级别的过期时间
     */
    public void expire(String key, long time) {
        redisTemplate.expire(key, time, TimeUnit.MINUTES);
    }

    /**
     * 根据key获取过期时间
     */
    public long getExpire(String key) {
        Long expireTime = redisTemplate.getExpire(key,TimeUnit.MINUTES);
        return Objects.isNull(expireTime) ? 0 :expireTime;
    }

    /**
     * 判断key是否存在
     */
    public boolean hasKey(String key) {
        Boolean hasKeyFlag = redisTemplate.hasKey(key);
        if (Objects.isNull(hasKeyFlag)) {
            return false;
        }
        return hasKeyFlag;
    }


    /**
     * 保存数据
     */
    public void saveStringByKey(String key, Object value) {
        redisTemplate.boundValueOps(key).set(value);

    }

    /**
     * 保存数据，指定生命周期（分钟）
     * @param key .
     * @param value .
     * @param expireTime .
     */
    public void saveStringByKey(String key, Object value, Long expireTime) {
        if (expireTime <= 0) {
            saveStringByKey(key, value);
        } else {
            redisTemplate.boundValueOps(key).set(value, expireTime, TimeUnit.MINUTES);
        }
    }


    /**
     * 保存int数据
     */
    public void saveIntegerByKey(String key, int value) {
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.boundValueOps(key).set(value);

    }


    /**
     * 保存数据
     * @param key .
     * @param value .
     * @param expireTime .
     */
    public void saveIntegerByKey(String key, int value, Long expireTime) {
        if (expireTime <= 0) {
            saveIntegerByKey(key, value);
        } else {
            redisTemplate.setValueSerializer(new StringRedisSerializer());
            redisTemplate.boundValueOps(key).set(value, expireTime, TimeUnit.MINUTES);

        }
    }

    /**
     * 保存double数据
     */
    public void saveDoubleByKey(String key, double value, Long expireTime) {
        String valueString = String.valueOf(value);
        if (expireTime <= 0) {
            saveStringByKey(key, valueString);
        } else {
            redisTemplate.setValueSerializer(new StringRedisSerializer());
            redisTemplate.boundValueOps(key).set(valueString, expireTime, TimeUnit.MINUTES);

        }
    }

    /**
     * 顺序的递增和递减
     *
     * @param value 增减根据数值的正负来判断
     */
    public void increment(String key, Long value) {
        redisTemplate.boundValueOps(key).increment(value);
    }


    /**
     * 获取key对应的字符数据
     */
    public String getStringByKey(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }

    /**
     * 获取key对应对象数据
     */
    public Object getObjectByKey(String key) {
        return redisTemplate.opsForValue().get(key);
    }


    /**
     * 添加一个Map集合
     */
    public void saveMapValue(String key, Map<String, ?> map, long expireTime) {
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.boundHashOps(key).putAll(map);
        if (expireTime > 0) {
            expire(key, expireTime);
        }
    }

    /**
     * 获取map中所有的keys
     */
    public Set<?> getMapKeys(String key) {
        return redisTemplate.boundHashOps(key).keys();
    }

    /**
     * 获取map中所有的values
     */
    public List<?> getMapValues(String key) {
        return redisTemplate.boundHashOps(key).values();
    }

    /**
     * 根据map中某个key获取对应的value
     */
    public Object getMapValueByMapKey(String redisKey, String mapKey) {
        return redisTemplate.boundHashOps(redisKey).get(mapKey);
    }

    /**
     * 根据map中的某个key删除对应的value
     */
    public void deleteMapValueByMapKey(String redisKey, String mapKey) {
        redisTemplate.boundHashOps(redisKey).delete(mapKey);
    }

    /**
     * 判断map中是否有指定的key
     */
    public boolean hasMapKey(String redisKey, String mapKey) {
        Boolean hasKey = redisTemplate.boundHashOps(redisKey).hasKey(mapKey);
        if (Objects.isNull(hasKey)) {
            return false;
        }
        return hasKey;
    }

    /**
     * 右存放List
     */
    public void saveRightListByKey(String key, List<?> values, long expireTime) {
        values.forEach(value -> redisTemplate.boundListOps(key).rightPush(value));
        if (expireTime > 0) {
            expire(key, expireTime);
        }
    }

    /**
     * 左存放List
     */
    public void saveLeftListByKey(String key, List<?> values, long expireTime) {
        values.forEach(value -> redisTemplate.boundListOps(key).leftPush(value));
        if (expireTime > 0) {
            expire(key, expireTime);
        }
    }

    /**
     * 获取List某范围的值
     *
     * @param start 起始索引
     * @param end   截止索引
     */
    public List<?> getListRangeValues(String key, long start, long end) {
        long size = getListSize(key);
        if (start > end) {
            start = 0;
            end = size;
        } else if (end < 0 || end > size) {
            end = size;
        } else if (start < 0 || start > size) {
            start = 0;
        }
        return redisTemplate.boundListOps(key).range(start, end);
    }

    /**
     * 获取List某范围的值
     */
    public List<?> getListAllValues(String key) {
        long size = getListSize(key);
        return redisTemplate.boundListOps(key).range(0, size);
    }

    /**
     * 根据指定索引获取指定value
     */
    public Object getListValueByIndex(String key, int index) {
        return redisTemplate.boundListOps(key).index(index);
    }

    /**
     * 获取list长度
     */
    public Long getListSize(String key) {
        return Objects.isNull(redisTemplate.boundListOps(key).size()) ? 0 : redisTemplate.boundListOps(key).size();
    }

    /**
     * 根据索引修改某个值
     */
    public void updateListValueByIndex(String key, int index, Object newObj) {
        redisTemplate.boundListOps(key).set(index, newObj);

    }


}
